import { DynamicModule, Provider, Type } from '@nestjs/common';
import { getDataSourceToken, TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
import { DataSource } from 'typeorm';
import { CUSTOM_REPOSITORY_METADATA } from './constants';
import { ExistConstraint } from 'src/Constraint/data.exist.constraint';
import { MatchConstraint } from 'src/Constraint/match.constraint';
import { PassWardConstraint } from 'src/Constraint/passward.constraint';
import { UniqueConstraint } from 'src/Constraint/unique.constraint';
export  class DatabaseModule {
    static forRoot(RegisterConfig: RegisterConfigType): DynamicModule {
        return {
            global: true,
            module: DatabaseModule,
            imports: [TypeOrmModule.forRoot(RegisterConfig())],
            providers: [
                ExistConstraint,
                MatchConstraint,
                PassWardConstraint,
                UniqueConstraint
            ],
        }
    }

    //T 接收都是个类 
    static forRepository<T extends Type<any>>(
        repositories: T[],
        dataSourceName?: string,
    ): DynamicModule {
        const Providers: Provider[] = []
        for (const Repo of repositories) {
            //自定义仓库的类装饰或取
            let entity = Reflect.getMetadata(CUSTOM_REPOSITORY_METADATA, Repo)
            if (!entity) {
                continue;
            }

            //getDataSourceToke
            Providers.push({
                inject: [getDataSourceToken(dataSourceName)],
                provide: Repo,
                useFactory: (dataSource: DataSource) => {
                    let base = dataSource.getRepository(entity)
                    return new Repo(base.target, base.manager, base.queryRunner);
                }

            })

        }
        
        /* 
        exports：表示需要导出的组件，即将 providers 数组中的组件导出供其他模块使用。
        module：表示这些组件所属的模块，即 DatabaseModule。
        providers：表示这些组件的提供者，即依赖注入容器中需要注册的组件。
        
        
        */
        return {
            exports: Providers,
            module: DatabaseModule,
            providers: Providers
        }

    }
}

type RegisterConfigType = () => TypeOrmModuleOptions